package com.zhoug.common3.filters;

import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;

import com.zhoug.common3.utils.LogUtils;

import java.util.Locale;
import java.util.regex.Pattern;

/**
 * 限制整数和小数位数
 *
 * @Author: zhoug
 * @Date: 2023/1/4
 * @Description:
 */
public class DecimalDigitsInputFilter implements InputFilter {
    private static final String TAG = ">>>DecimalDigitsInputFilter";
    private static boolean DEBUG = true;
    private static final int DEF_INTEGER_DIGITS = -1;//整数位不限制
    private static final int DEF_DECIMAL_DIGITS = 2;//小数位默认2位
    /**
     * 最大长度限制,否则正则表达式报错:Decimal number is too large near index 20
     */
    private static final int MAX_DIGITS = 20;
    private static Pattern numberPatter = Pattern.compile("^[0-9|.]*$");
    /**
     * 限制整数和小数位数,负数表示不限制
     */
    private int integerDigits = -1;//整数位数
    private int decimalDigits = 2;//小数位数
    /**
     * 最大值
     */
    private double max = Double.MIN_VALUE;


    private Pattern mPattern;

    public DecimalDigitsInputFilter() {
        this(DEF_INTEGER_DIGITS, DEF_DECIMAL_DIGITS);
    }

    /**
     * @param decimalDigits 小数位数 负数表示不限制
     */
    public DecimalDigitsInputFilter(int decimalDigits) {
        this(DEF_INTEGER_DIGITS, decimalDigits);
    }

    /**
     * @param integerDigits 整数位数 负数表示不限制
     * @param decimalDigits 小数位数 负数表示不限制
     */
    public DecimalDigitsInputFilter(int integerDigits, int decimalDigits) {
        this.integerDigits = integerDigits;
        this.decimalDigits = decimalDigits;
        initPattern();
    }


    /**
     * @param integerDigits 整数位数 负数表示不限制
     */
    public DecimalDigitsInputFilter setIntegerDigits(int integerDigits) {
        if (this.integerDigits != integerDigits) {
            this.integerDigits = integerDigits;
            initPattern();
        }
        return this;
    }

    /**
     * @param decimalDigits 小数位数 负数表示不限制
     */
    public DecimalDigitsInputFilter setDecimalDigits(int decimalDigits) {
        if (this.decimalDigits != decimalDigits) {
            this.decimalDigits = decimalDigits;
            initPattern();
        }
        return this;
    }

    public DecimalDigitsInputFilter setMax(double max) {
        this.max = max;
        return this;
    }


    private void initPattern() {
        int maxIntegerDigits = integerDigits >= 0 ? integerDigits : MAX_DIGITS;
        if (decimalDigits == 0) {
            //没有小数位不能输入点"."
            String regex = String.format(Locale.CANADA, "[0-9]{0,%d}+", maxIntegerDigits);
            mPattern = Pattern.compile(regex);
        } else {
            int maxDecimalDigits = decimalDigits >= 0 ? decimalDigits : MAX_DIGITS;
            String regex = String.format(Locale.CANADA, "[0-9]{0,%d}+(\\.[0-9]{0,%d})?", maxIntegerDigits, maxDecimalDigits);
            mPattern = Pattern.compile(regex);
        }
    }

    /**
     * 当缓冲区要使用source的[start - end)范围内的内容替换dest的[dstart - dend)范围内的内容
     *
     * @param source 输入的内容,若是删除动作，则为空字符
     * @param start  source对应的起始索引，始终为0
     * @param end    source对应的结尾索引，为source的length-1
     * @param dest   当前输入框中显示的内容
     * @param dstart 被贴换的内容在输入框中的起始位置(包含)
     * @param dend   被贴换的内容在输入框中的结束位置(不包含)
     * @return 返回null:表示接受原本的输入source;返回空字符串"":放弃本次输入,删除操作不会过滤掉;返回指定内容
     */
    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        if (DEBUG) {
            LogUtils.d(TAG, "source:" + source + ",start:" + start + ",end:" + end + ",dest:" + dest + ",dstart:" + dstart + ",dend:" + dend);
        }
        String sourceText = source.toString();
        //去掉空格
        sourceText = sourceText.replaceAll(" ", "");
        //只能包含数字
        if (sourceText.length() != 0 && !numberPatter.matcher(sourceText).matches()) {
            if (DEBUG) {
                LogUtils.d(TAG, "输入内容不是数字");
            }
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder(dest);
        stringBuilder.replace(dstart, dend, sourceText);
        String result = stringBuilder.toString();
        if (DEBUG) {
            LogUtils.d(TAG, "result:" + result);
        }
        boolean matches = mPattern.matcher(result).matches();
        if (matches && max != Double.MIN_VALUE ) {
            if (TextUtils.isEmpty(result)) {
                return "";
            }
            double re = 0;
            try {
                re = Double.parseDouble(result);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
            if (max != Double.MIN_VALUE) {
                matches = re <= max;
            }
        }

        if (!matches) {
            if (DEBUG) {
                LogUtils.d(TAG, "输入后不匹配");
            }
            //通过添加已删除的内容达到不删除的效果
            if (start == 0 && end == 0 && dend > dstart) {
                return dest.subSequence(dstart, dend);
            }
            return "";
        }
        return sourceText;
    }
}
